package cn.com.codes.ldapVerification.util;

import java.util.Hashtable;
import java.util.List;

import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.ldap.Control;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;

import org.apache.log4j.Logger;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;

import cn.com.codes.ldapConfigInfo.service.LdapConfigInfoService;
import cn.com.codes.ldapVerification.dto.LdapVerificationDto;
import cn.com.codes.object.LdapConfigInfo;

public class LdapInitUtil implements ApplicationListener {
//	
	private static Logger logger = Logger.getLogger(LdapInitUtil.class);
	private static LdapContext ldapDataBase;
	private LdapConfigInfoService ldapConfigInfoService;




	/**
	 * @param dto 项目启动后，执行此方法，加载服务配置信息，验证和连接ldap
	 */
	@SuppressWarnings("unchecked")
	public void ldapConnectInit(LdapVerificationDto dto){
		List<LdapConfigInfo> ldapConfigInfos = ldapConfigInfoService.findBySql("select * from t_ldap_config_info t WHERE t.enable = ? ", LdapConfigInfo.class, "1");
		if(null != ldapConfigInfos && ldapConfigInfos.size() > 0){
			LdapConfigInfo ldapConfigInfo = ldapConfigInfos.get(0);
			dto.setLdapConfigInfo(ldapConfigInfo);
			
			LdapContext ldapContext = LdapInitUtil.ldapInitConnectByManagr(dto);
			if(null != ldapContext){
				ldapDataBase = LdapInitUtil.connectLdapDataBase(dto);
				LdapInitUtil.setLdapDataBase(ldapDataBase);
			}
		}
	}
	
	
	/**
	 * @param dto 服务配置信息更换，切换为启动，重新验证和连接
	 */
	public void ldapConfigInfoEditStartEnable(LdapVerificationDto dto){
		LdapContext ldapContext = LdapInitUtil.ldapInitConnectByManagr(dto);
		if(null != ldapContext){
			ldapDataBase = LdapInitUtil.connectLdapDataBase(dto);
			LdapInitUtil.setLdapDataBase(ldapDataBase);
		}else{
			LdapInitUtil.setLdapDataBase(ldapContext);
			logger.info("请检查你的服务配置信息，不能进行ldap验证!");
		}
	}
	
	
	public static LdapContext connectLdapDataBase(LdapVerificationDto dto) {
		Hashtable<String, String> env = new Hashtable<String, String>();
		LdapContext ctx = null;
		env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
		env.put(Context.PROVIDER_URL,"ldap://"+dto.getLdapConfigInfo().getServerIp());
		env.put(Context.SECURITY_AUTHENTICATION, "simple");
		env.put(Context.SECURITY_PRINCIPAL, dto.getLdapConfigInfo().getBaseDn());
		env.put(Context.SECURITY_CREDENTIALS, dto.getLdapConfigInfo().getBindPassword());
		try {
			ctx = new InitialLdapContext(env,null);
		} catch (NamingException e) {
			e.printStackTrace();
		}
		
		return ctx;
	}
	
	/**
	 * 认证通过，管理员dn、密码
	 * @param dto
	 * @return
	 */
	public static LdapContext ldapInitConnectByManagr(LdapVerificationDto dto){
		Hashtable<String, String> env = new Hashtable<String, String>();
		LdapContext ctx = null;
	    Control[] connCtls = null;
	    
	    	
	    	if(null != dto.getLdapConfigInfo()){
	    		String url = "ldap://" + dto.getLdapConfigInfo().getServerIp()+":"+dto.getLdapConfigInfo().getPort()+"/";
	    		String baseDN = dto.getLdapConfigInfo().getBaseDn();
	    		String bindPassword = dto.getLdapConfigInfo().getBindPassword();
	    		
	    		env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
	    		env.put(Context.PROVIDER_URL, url + baseDN);
	    		env.put(Context.SECURITY_AUTHENTICATION, "simple");
	    		env.put(Context.SECURITY_PRINCIPAL, baseDN);
	    		env.put(Context.SECURITY_CREDENTIALS, bindPassword);
	    		
	    		env.put("java.naming.batchsize", "50");
	    		env.put("com.sun.jndi.ldap.connect.timeout", "3000");
	    		env.put("com.sun.jndi.ldap.connect.pool", "true");
	    		env.put("com.sun.jndi.ldap.connect.pool.maxsize", "3");
	    		env.put("com.sun.jndi.ldap.connect.pool.prefsize", "1");
	    		env.put("com.sun.jndi.ldap.connect.pool.timeout", "300000");
	    		env.put("com.sun.jndi.ldap.connect.pool.initsize", "1");
	    		env.put("com.sun.jndi.ldap.connect.pool.authentication", "simple");
	    		
	    		
	    		try {
	    			ctx = new InitialLdapContext(env, connCtls);
	    			System.out.println("认证成功!");
	    		} catch (javax.naming.AuthenticationException e) {
	    			System.out.println("认证失败!");
	    			e.printStackTrace();
	    		} catch (Exception e) {
	    			System.out.println("认证出错!");
	    			e.printStackTrace();
	    		}
	    		
	    	}
	    

		return ctx;
	}
	
	public static LdapContext getLdapDataBase() {
		return ldapDataBase;
	}

	public static void setLdapDataBase(LdapContext ldapDataBase) {
		LdapInitUtil.ldapDataBase = ldapDataBase;
	}


	public LdapConfigInfoService getLdapConfigInfoService() {
		return ldapConfigInfoService;
	}


	public void setLdapConfigInfoService(LdapConfigInfoService ldapConfigInfoService) {
		this.ldapConfigInfoService = ldapConfigInfoService;
	}


	@Override
	public void onApplicationEvent(ApplicationEvent arg0) {
		LdapVerificationDto dto = new LdapVerificationDto();
		ldapConnectInit(dto);
	}
	
}
